package com.hlf.modules.api.service.impl;

import com.hlf.common.constants.Constants;
import com.hlf.common.exception.BusinessException;
import com.hlf.common.utils.IdWorkerFactory;
import com.hlf.common.utils.ReturnResult;
import com.hlf.modules.api.entity.Queue;
import com.hlf.modules.api.mapper.QueueMapper;
import com.hlf.modules.api.service.QueueService;
import com.hlf.modules.merchant.store.entity.Store;
import com.hlf.modules.merchant.store.mapper.StoreMapper;
import com.hlf.modules.merchant.table.entity.TableType;
import com.hlf.modules.merchant.table.mapper.TableTypeMapper;
import com.hlf.modules.sys.entity.SysUserEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 排队服务层
 */
@Service
public class QueueServiceImpl implements QueueService {

    @Autowired
    private QueueMapper queueMapper;
    @Autowired
    private TableTypeMapper tableTypeMapper;
    @Autowired
    private StoreMapper storeMapper;

    /**
     * 排队列表
     *
     * @param storeId
     * @return
     */
    @Override
    public List<TableType> queueList(String storeId) {

        //查本店所有餐桌类型
        List<TableType> tableTypes = tableTypeMapper.queryListForStoreId(Long.parseLong(storeId));

        List<Queue> queues = queueMapper.selectByStoreId(Long.parseLong(storeId));
        Map<Long, List<Queue>> map = queues.stream().collect(Collectors.groupingBy(Queue::getTableTypeId));
        for (TableType tableType : tableTypes) {
            List<Queue> list = map.get(tableType.getId());
            if (list == null) {
                tableType.setCurrentSerialNumber(0L);
                continue;
            }
            Long serialNumberStore = list.stream().collect(Collectors.minBy(Comparator.comparing(Queue::getSerialNumberType))).get().getSerialNumberStore();
            tableType.setCurrentSerialNumber(serialNumberStore);
            String num = "A" + String.format("%03d", serialNumberStore);
            tableType.setCurrentSerialNumberStr(num);
            tableType.setSerialSum(list.size() - 1);
        }
        return tableTypes;
    }

    /**
     * 取号
     *
     * @param
     * @param tableTypeId
     */
    @Override
    @Transactional
    public synchronized Map<String, Object> getNum(SysUserEntity user, String tableTypeId) {

        Long userId = user.getUserId();
        String storeId = user.getCurrentStoreId();
        Store store = storeMapper.queryObject(storeId);
        if (store == null) {
            throw new BusinessException("该门店未找到!");
        }
        List<Queue> queues = queueMapper.selectCurrentLast(Long.parseLong(storeId), Long.parseLong(tableTypeId));
        Queue lastQueue = null;
        if (queues != null && queues.size() != 0) {
            lastQueue = queues.stream().collect(Collectors.maxBy(Comparator.comparing(Queue::getSerialNumberType))).get();
        }

        if (lastQueue == null) {
            //查出本店最大号码
            Long serialNumberStore = null;
            List<Queue> queuesByStore = queueMapper.selectByStoreIdAll(Long.parseLong(storeId));
            if (queuesByStore != null && queuesByStore.size() > 0) {
                serialNumberStore = queuesByStore.stream().collect(Collectors.maxBy
                        (Comparator.comparing(Queue::getSerialNumberStore))).get().getSerialNumberStore();
            }
            lastQueue = new Queue();
            lastQueue.setId(IdWorkerFactory.nextId());
            lastQueue.setInsertBy(userId);
            lastQueue.setSerialNumberType(1L);
            lastQueue.setSerialNumberStore(1L + (serialNumberStore == null ? 0 : serialNumberStore));
            lastQueue.setStoreId(Long.parseLong(storeId));
            lastQueue.setTableTypeId(Long.parseLong(tableTypeId));
        } else {
            lastQueue.setId(IdWorkerFactory.nextId());
            lastQueue.setInsertBy(userId);
            lastQueue.setSerialNumberType(lastQueue.getSerialNumberType() + 1);
            lastQueue.setSerialNumberStore(lastQueue.getSerialNumberStore() + 1);
        }
        lastQueue.setDailyNum(store.getQueueDailyNum());
        try {
            queueMapper.insertSelective(lastQueue);
        } catch (Exception e) {
            throw new BusinessException("抱歉,这个号码已被取,请重新取号!");
        }

        /**
         * 调用打印机
         */
        Map<String, Object> map = new HashMap<>();
        String num = "A" + String.format("%03d", lastQueue.getSerialNumberStore());
        map.put("serialNumber", num);
        map.put("serialSum", queues.size());
        return map;
    }

    /**
     * 叫号
     *
     * @param tableTypeId
     * @param serialNumber
     */
    @Override
    public ReturnResult findNum(SysUserEntity user, String tableTypeId, String serialNumber) {
        Long num = Long.parseLong(serialNumber.substring(1));
        Queue queue = queueMapper.selectObj(Long.parseLong(user.getCurrentStoreId()), Long.parseLong(tableTypeId), num);
        if (queue == null) {
            throw new BusinessException("当前序号已过期!");
        }
        Map<String, Object> map = new HashMap<>();
        map.put("serialNumber", queue.getSerialNumberStore());
        return ReturnResult.ok().put(Constants.DEFAULT_RESULT_NAME, map);
    }

    /**
     * 下一位
     *
     * @param user
     * @param tableTypeId
     * @param serialNumber
     */
    @Override
    @Transactional
    public void next(SysUserEntity user, String tableTypeId, String serialNumber) {
        Long num = Long.parseLong(serialNumber.substring(1));
        List<Queue> queues = queueMapper.selectCurrentLast(Long.parseLong(user.getCurrentStoreId()), Long.parseLong(tableTypeId));
        Queue queue = queues.stream().collect(Collectors.minBy(Comparator.comparing(Queue::getSerialNumberType))).get();
        Long serialNumberStore = queue.getSerialNumberStore();
        if (serialNumberStore == null) {
            throw new BusinessException("当前序号已过期!");
        }
        if (serialNumberStore.equals(num)) {
            queueMapper.updateDelByPrimaryKey(queue.getId());
        } else {
            throw new BusinessException("当前序号已过期!");
        }
    }

    /**
     * 每日删除旧排队号
     *
     * @return
     */
    @Override
    public void dailiDelete() {
        List<Queue> queues = queueMapper.dailyQueryAll();
        for (Queue queue : queues) {
            queueMapper.deleteByPrimaryKey(queue.getId());
        }
    }

    /**
     * 打开或关闭每日清除编号开关
     *
     * @param dailyNum
     * @return
     */
    @Override
    @Transactional
    public ReturnResult openOrClose(SysUserEntity user, Byte dailyNum) {
        Store store = new Store();
        store.setId(Long.parseLong(user.getCurrentStoreId()));
        store.setQueueDailyNum(dailyNum);
        int i = storeMapper.updateByPrimaryKeySelective(store);
        if (i == 0){
            throw new BusinessException("打开或关闭失败!");
        }
        queueMapper.updateDailyNumByStoreId(user.getCurrentStoreId(), dailyNum);
        return ReturnResult.ok();
    }

    @Override
    public ReturnResult queryStatus(String currentStoreId) {
        Store store = storeMapper.queryObject(currentStoreId);
        Map<String, Object> map = new HashMap<>();
        map.put("dailyNum", store.getQueueDailyNum());
        return ReturnResult.ok().put(Constants.DEFAULT_RESULT_NAME, map);
    }
}
